{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "46ee116a-59fe-41a1-86f6-05b44b3ce8ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 官网地址：https://platform.openai.com/docs/api-reference/assistants"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "478c301d-b042-4779-a118-f5fbcdd83e21",
   "metadata": {},
   "outputs": [],
   "source": [
    "from openai import OpenAI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a2346314-38ec-4d4c-96d6-f590b0bc0a2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "GPT_MODEL = \"gpt-4o-mini\"\n",
    "# api_key = os.getenv(\"OPENAI_API_KEY\")\n",
    "api_key = \"sk-y7DHfp9fzuCxOVm2158638099f9541D3833aB4F4Ed674aCf\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "175824a0-5527-47bd-a4f8-2e9a3b8c4250",
   "metadata": {},
   "outputs": [],
   "source": [
    "client = OpenAI(\n",
    "    api_key=\"sk-y7DHfp9fzuCxOVm2158638099f9541D3833aB4F4Ed674aCf\", # 你的KEY\n",
    "    base_url=\"https://vip.apiyi.com/v1\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3d08256d-2e08-42d2-bc43-daad968fe818",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "ename": "InternalServerError",
     "evalue": "Error code: 501 - {'error': {'message': 'API not implemented', 'localized_message': '', 'type': 'shell_api_error', 'param': '', 'code': 'api_not_implemented'}}",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mInternalServerError\u001b[0m                       Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[6], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m my_assistant \u001b[38;5;241m=\u001b[39m client\u001b[38;5;241m.\u001b[39mbeta\u001b[38;5;241m.\u001b[39massistants\u001b[38;5;241m.\u001b[39mcreate(\n\u001b[0;32m      2\u001b[0m     instructions\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYou are a personal math tutor. When asked a question, write and run Python code to answer the question.\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m      3\u001b[0m     name\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mMath Tutor\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m      4\u001b[0m     tools\u001b[38;5;241m=\u001b[39m[{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtype\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcode_interpreter\u001b[39m\u001b[38;5;124m\"\u001b[39m}],\n\u001b[0;32m      5\u001b[0m     model\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgpt-4o\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m      6\u001b[0m )\n\u001b[0;32m      7\u001b[0m \u001b[38;5;28mprint\u001b[39m(my_assistant)\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\resources\\beta\\assistants\\assistants.py:112\u001b[0m, in \u001b[0;36mAssistants.create\u001b[1;34m(self, model, description, file_ids, instructions, metadata, name, tools, extra_headers, extra_query, extra_body, timeout)\u001b[0m\n\u001b[0;32m     74\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m     75\u001b[0m \u001b[38;5;124;03mCreate an assistant with a model and instructions.\u001b[39;00m\n\u001b[0;32m     76\u001b[0m \n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    109\u001b[0m \u001b[38;5;124;03m  timeout: Override the client-level default timeout for this request, in seconds\u001b[39;00m\n\u001b[0;32m    110\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m    111\u001b[0m extra_headers \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOpenAI-Beta\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124massistants=v1\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m(extra_headers \u001b[38;5;129;01mor\u001b[39;00m {})}\n\u001b[1;32m--> 112\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_post(\n\u001b[0;32m    113\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/assistants\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m    114\u001b[0m     body\u001b[38;5;241m=\u001b[39mmaybe_transform(\n\u001b[0;32m    115\u001b[0m         {\n\u001b[0;32m    116\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m: model,\n\u001b[0;32m    117\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdescription\u001b[39m\u001b[38;5;124m\"\u001b[39m: description,\n\u001b[0;32m    118\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfile_ids\u001b[39m\u001b[38;5;124m\"\u001b[39m: file_ids,\n\u001b[0;32m    119\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minstructions\u001b[39m\u001b[38;5;124m\"\u001b[39m: instructions,\n\u001b[0;32m    120\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmetadata\u001b[39m\u001b[38;5;124m\"\u001b[39m: metadata,\n\u001b[0;32m    121\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m: name,\n\u001b[0;32m    122\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtools\u001b[39m\u001b[38;5;124m\"\u001b[39m: tools,\n\u001b[0;32m    123\u001b[0m         },\n\u001b[0;32m    124\u001b[0m         assistant_create_params\u001b[38;5;241m.\u001b[39mAssistantCreateParams,\n\u001b[0;32m    125\u001b[0m     ),\n\u001b[0;32m    126\u001b[0m     options\u001b[38;5;241m=\u001b[39mmake_request_options(\n\u001b[0;32m    127\u001b[0m         extra_headers\u001b[38;5;241m=\u001b[39mextra_headers, extra_query\u001b[38;5;241m=\u001b[39mextra_query, extra_body\u001b[38;5;241m=\u001b[39mextra_body, timeout\u001b[38;5;241m=\u001b[39mtimeout\n\u001b[0;32m    128\u001b[0m     ),\n\u001b[0;32m    129\u001b[0m     cast_to\u001b[38;5;241m=\u001b[39mAssistant,\n\u001b[0;32m    130\u001b[0m )\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\_base_client.py:1208\u001b[0m, in \u001b[0;36mSyncAPIClient.post\u001b[1;34m(self, path, cast_to, body, options, files, stream, stream_cls)\u001b[0m\n\u001b[0;32m   1194\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpost\u001b[39m(\n\u001b[0;32m   1195\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   1196\u001b[0m     path: \u001b[38;5;28mstr\u001b[39m,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1203\u001b[0m     stream_cls: \u001b[38;5;28mtype\u001b[39m[_StreamT] \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1204\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m ResponseT \u001b[38;5;241m|\u001b[39m _StreamT:\n\u001b[0;32m   1205\u001b[0m     opts \u001b[38;5;241m=\u001b[39m FinalRequestOptions\u001b[38;5;241m.\u001b[39mconstruct(\n\u001b[0;32m   1206\u001b[0m         method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpost\u001b[39m\u001b[38;5;124m\"\u001b[39m, url\u001b[38;5;241m=\u001b[39mpath, json_data\u001b[38;5;241m=\u001b[39mbody, files\u001b[38;5;241m=\u001b[39mto_httpx_files(files), \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39moptions\n\u001b[0;32m   1207\u001b[0m     )\n\u001b[1;32m-> 1208\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m cast(ResponseT, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrequest(cast_to, opts, stream\u001b[38;5;241m=\u001b[39mstream, stream_cls\u001b[38;5;241m=\u001b[39mstream_cls))\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\_base_client.py:897\u001b[0m, in \u001b[0;36mSyncAPIClient.request\u001b[1;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[0;32m    888\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrequest\u001b[39m(\n\u001b[0;32m    889\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m    890\u001b[0m     cast_to: Type[ResponseT],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    895\u001b[0m     stream_cls: \u001b[38;5;28mtype\u001b[39m[_StreamT] \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m    896\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m ResponseT \u001b[38;5;241m|\u001b[39m _StreamT:\n\u001b[1;32m--> 897\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request(\n\u001b[0;32m    898\u001b[0m         cast_to\u001b[38;5;241m=\u001b[39mcast_to,\n\u001b[0;32m    899\u001b[0m         options\u001b[38;5;241m=\u001b[39moptions,\n\u001b[0;32m    900\u001b[0m         stream\u001b[38;5;241m=\u001b[39mstream,\n\u001b[0;32m    901\u001b[0m         stream_cls\u001b[38;5;241m=\u001b[39mstream_cls,\n\u001b[0;32m    902\u001b[0m         remaining_retries\u001b[38;5;241m=\u001b[39mremaining_retries,\n\u001b[0;32m    903\u001b[0m     )\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\_base_client.py:973\u001b[0m, in \u001b[0;36mSyncAPIClient._request\u001b[1;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[0;32m    971\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m retries \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_should_retry(err\u001b[38;5;241m.\u001b[39mresponse):\n\u001b[0;32m    972\u001b[0m     err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mclose()\n\u001b[1;32m--> 973\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_retry_request(\n\u001b[0;32m    974\u001b[0m         options,\n\u001b[0;32m    975\u001b[0m         cast_to,\n\u001b[0;32m    976\u001b[0m         retries,\n\u001b[0;32m    977\u001b[0m         err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mheaders,\n\u001b[0;32m    978\u001b[0m         stream\u001b[38;5;241m=\u001b[39mstream,\n\u001b[0;32m    979\u001b[0m         stream_cls\u001b[38;5;241m=\u001b[39mstream_cls,\n\u001b[0;32m    980\u001b[0m     )\n\u001b[0;32m    982\u001b[0m \u001b[38;5;66;03m# If the response is streamed then we need to explicitly read the response\u001b[39;00m\n\u001b[0;32m    983\u001b[0m \u001b[38;5;66;03m# to completion before attempting to access the response text.\u001b[39;00m\n\u001b[0;32m    984\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mis_closed:\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\_base_client.py:1021\u001b[0m, in \u001b[0;36mSyncAPIClient._retry_request\u001b[1;34m(self, options, cast_to, remaining_retries, response_headers, stream, stream_cls)\u001b[0m\n\u001b[0;32m   1017\u001b[0m \u001b[38;5;66;03m# In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a\u001b[39;00m\n\u001b[0;32m   1018\u001b[0m \u001b[38;5;66;03m# different thread if necessary.\u001b[39;00m\n\u001b[0;32m   1019\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(timeout)\n\u001b[1;32m-> 1021\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request(\n\u001b[0;32m   1022\u001b[0m     options\u001b[38;5;241m=\u001b[39moptions,\n\u001b[0;32m   1023\u001b[0m     cast_to\u001b[38;5;241m=\u001b[39mcast_to,\n\u001b[0;32m   1024\u001b[0m     remaining_retries\u001b[38;5;241m=\u001b[39mremaining,\n\u001b[0;32m   1025\u001b[0m     stream\u001b[38;5;241m=\u001b[39mstream,\n\u001b[0;32m   1026\u001b[0m     stream_cls\u001b[38;5;241m=\u001b[39mstream_cls,\n\u001b[0;32m   1027\u001b[0m )\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\_base_client.py:973\u001b[0m, in \u001b[0;36mSyncAPIClient._request\u001b[1;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[0;32m    971\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m retries \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_should_retry(err\u001b[38;5;241m.\u001b[39mresponse):\n\u001b[0;32m    972\u001b[0m     err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mclose()\n\u001b[1;32m--> 973\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_retry_request(\n\u001b[0;32m    974\u001b[0m         options,\n\u001b[0;32m    975\u001b[0m         cast_to,\n\u001b[0;32m    976\u001b[0m         retries,\n\u001b[0;32m    977\u001b[0m         err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mheaders,\n\u001b[0;32m    978\u001b[0m         stream\u001b[38;5;241m=\u001b[39mstream,\n\u001b[0;32m    979\u001b[0m         stream_cls\u001b[38;5;241m=\u001b[39mstream_cls,\n\u001b[0;32m    980\u001b[0m     )\n\u001b[0;32m    982\u001b[0m \u001b[38;5;66;03m# If the response is streamed then we need to explicitly read the response\u001b[39;00m\n\u001b[0;32m    983\u001b[0m \u001b[38;5;66;03m# to completion before attempting to access the response text.\u001b[39;00m\n\u001b[0;32m    984\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mis_closed:\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\_base_client.py:1021\u001b[0m, in \u001b[0;36mSyncAPIClient._retry_request\u001b[1;34m(self, options, cast_to, remaining_retries, response_headers, stream, stream_cls)\u001b[0m\n\u001b[0;32m   1017\u001b[0m \u001b[38;5;66;03m# In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a\u001b[39;00m\n\u001b[0;32m   1018\u001b[0m \u001b[38;5;66;03m# different thread if necessary.\u001b[39;00m\n\u001b[0;32m   1019\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(timeout)\n\u001b[1;32m-> 1021\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request(\n\u001b[0;32m   1022\u001b[0m     options\u001b[38;5;241m=\u001b[39moptions,\n\u001b[0;32m   1023\u001b[0m     cast_to\u001b[38;5;241m=\u001b[39mcast_to,\n\u001b[0;32m   1024\u001b[0m     remaining_retries\u001b[38;5;241m=\u001b[39mremaining,\n\u001b[0;32m   1025\u001b[0m     stream\u001b[38;5;241m=\u001b[39mstream,\n\u001b[0;32m   1026\u001b[0m     stream_cls\u001b[38;5;241m=\u001b[39mstream_cls,\n\u001b[0;32m   1027\u001b[0m )\n",
      "File \u001b[1;32mD:\\Java\\miniconda3\\envs\\langChain\\Lib\\site-packages\\openai\\_base_client.py:988\u001b[0m, in \u001b[0;36mSyncAPIClient._request\u001b[1;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[0;32m    985\u001b[0m         err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mread()\n\u001b[0;32m    987\u001b[0m     log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRe-raising status error\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m--> 988\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_make_status_error_from_response(err\u001b[38;5;241m.\u001b[39mresponse) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m    990\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_response(\n\u001b[0;32m    991\u001b[0m     cast_to\u001b[38;5;241m=\u001b[39mcast_to,\n\u001b[0;32m    992\u001b[0m     options\u001b[38;5;241m=\u001b[39moptions,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    995\u001b[0m     stream_cls\u001b[38;5;241m=\u001b[39mstream_cls,\n\u001b[0;32m    996\u001b[0m )\n",
      "\u001b[1;31mInternalServerError\u001b[0m: Error code: 501 - {'error': {'message': 'API not implemented', 'localized_message': '', 'type': 'shell_api_error', 'param': '', 'code': 'api_not_implemented'}}"
     ]
    }
   ],
   "source": [
    "# 中转接口不支持assistants接口\n",
    "my_assistant = client.beta.assistants.create(\n",
    "    instructions=\"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n",
    "    name=\"Math Tutor\",\n",
    "    tools=[{\"type\": \"code_interpreter\"}],\n",
    "    model=\"gpt-4o\",\n",
    ")\n",
    "print(my_assistant)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6ead12e3-7e3a-4f7e-b1e6-d8585f27bd7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个交流线程\n",
    "thread = client.beta.threads.create()\n",
    "\n",
    "# 在线程中创建一条用户消息，并提交一个数学问题\n",
    "message = client.beta.threads.messages.create(\n",
    "    thread_id=thread.id,\n",
    "    role=\"user\",\n",
    "    content:\"I need to solve the equation `3x + 11 = 14`. Can you help me?\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cb03bb91-0c5f-4195-927a-b23d28b93303",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 等待消息结果，并处理消息返回内容\n",
    "\n",
    "# 创建并等待执行流完成，用于处理该线程中的交互和问题解答\n",
    "run = client.beta.threads.runs.create_and_poll(\n",
    "    thread_id=thread.id,\n",
    "    assistant_id=my_assistant.id,\n",
    "    instructions=\"Please address the user as Jane Doe. The user has a premium account.\"\n",
    ")\n",
    "\n",
    "# 打印执行流的完成状态\n",
    "print(\"Run completed with status: \" + run.status)\n",
    "\n",
    "if run.status == \"completed\":\n",
    "    messages = client.beta.threads.messages.list(thread_id=thread.id)\n",
    "\n",
    "    for message in messages:\n",
    "        assert message.content[0].type == \"text\"\n",
    "        print(f\"Role:{message.role.capitalize()}\")  # 角色名称首字母大写\n",
    "        print(\"Message:\")\n",
    "        print(message.content[0].text.value + \"\\n\")  # 输出消息内容，并换行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11836e7c-90f8-41eb-8757-d15f7d022119",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 流式处理消息体\n",
    "from typing_extensions import override\n",
    "from openai import AssistentEventHandler\n",
    "from openai\n",
    "\n",
    "class EventHandler(AssistantEventHandler):\n",
    "    @override\n",
    "    def on_text_created(self, text) -> None:\n",
    "        print(f\"\\nassistant > \", end=\"\", flush=True)\n",
    "\n",
    "    @override\n",
    "    def on_text_delta(self, delta, snapshot):\n",
    "        print(delta.value, end=\"\", flush=True)\n",
    "\n",
    "    def on_tool_call_created(self, tool_call):\n",
    "        print(f\"\\nassistant > {tool_call.type}\\n\", flush=True)\n",
    "\n",
    "    def on_tool_call_delta(self, delta, snapshot):\n",
    "        if delta.type == \"code_interpreter\":\n",
    "            if delta.code_interpreter.input:\n",
    "                print(delta.code_interpreter.input, end=\"\", flush=True)\n",
    "            if delta.code_interpreter.outputs:\n",
    "                print(\"\\noutput > \", flush=True)\n",
    "                for output in delta.code_interpreter.outputs:\n",
    "                    if output.type == \"logs\":\n",
    "                        print(f\"\\n{output.logs}\", flush=True)\n",
    "\n",
    "with client.beta.threads.runs.stream(\n",
    "    thread_id=thread.id,\n",
    "    assistant_id=assistant.id,\n",
    "    instructions=\"Please address the user as Jane Doe. The user has a premium account.\",\n",
    "    event_handler=EventHandler(),\n",
    ") as stream:\n",
    "    stream.until_done()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "54c51311-6949-48d9-af85-60cbf15ec5ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 删除创建的助手\n",
    "client.beta.assistants.delete(assistant.id)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "442c2601-ad4d-46c0-82c0-800235627492",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b704ff61-31fd-4cdf-9238-267ce8438438",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6443c24b-6f77-445d-8e05-416efc151989",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d8d0c4d-221e-46ef-ba99-435eb05e60ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 开发python代码小助手\n",
    "\n",
    "import openai  # 导入 openai 库\n",
    "import time\n",
    "\n",
    "# 从环境变量 OPENAI_API_KEY 中获取 API 密钥\n",
    "client = openai.OpenAI()\n",
    "\n",
    "# 创建一个名为 \"Python Master\" 的助手，它能根据需求生成可以运行的 Python 代码\n",
    "assistant_python = client.beta.assistants.create(\n",
    "    name=\"Python Master\",\n",
    "    instructions=\"You are a Python Expert. Generate runnable Python code according to messages.\",\n",
    "    tools=[{\"type\": \"code_interpreter\"}],  # 使用工具：代码解释器\n",
    "    model=\"gpt-4o\",  # 使用模型： GPT-4\n",
    ")\n",
    "\n",
    "# 创建一个交流线程\n",
    "thread_python = client.beta.threads.create()\n",
    "print(assistant_python.id)\n",
    "print(thread_python.id)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03c501d2-27b8-4be0-ae0b-f1f685141849",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在该线程中创建一条信息\n",
    "message = client.beta.threads.messages.create(\n",
    "    thread_id=thread_python.id,\n",
    "    role=\"user\",\n",
    "    content=\"快速排序咋个写？\",\n",
    ")\n",
    "print(message.id)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "229a4f35-ad5f-4b04-84ab-dbeb33c09cdf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建并等待执行流完成，用于处理该线程中的交互和问题解答\n",
    "# 方式一：create_and_poll创建并轮询方式\n",
    "run = client.beta.threads.runs.create_and_poll(\n",
    "    thread_id=thread_python.id,\n",
    "    assistant_id=assistant_python.id,\n",
    ")\n",
    "\n",
    "print(run.id)\n",
    "print(\"Run completed with status: \" + run.status)  # 打印执行流的完成状态\n",
    "\n",
    "# 如果执行流状态为 \"completed\"（已完成），则获取并打印所有消息\n",
    "if run.status == \"completed\":\n",
    "    messages = client.beta.threads.messages.list(thread_id=thread_python.id)\n",
    "\n",
    "    print(\"\\nMessages:\\n\")\n",
    "    for message in messages:\n",
    "        assert message.content[0].type == \"text\"\n",
    "        print(f\"Role: {message.role.capitalize()}\")  # 角色名称首字母大写\n",
    "        print(\"Message:\")\n",
    "        print(message.content[0].text.value + \"\\n\")  # 每条消息后添加空行以增加可读性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a457d057-f70d-4f65-bbee-90392cad5fdb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 方式二：create 和 retrieve方式，判断run状态为（初始为queued）\n",
    "run2 = client.beta.threads.runs.create(\n",
    "    thread_id=thread_python.id,\n",
    "    assistant_id=assistant_python.id,\n",
    ")\n",
    "print(run2.id)\n",
    "print(\"Run初始状态 \" + run2.status)  # 打印执行流的完成状态\n",
    "\n",
    "while run2.status == \"queued\" or run.status == \"in_progress\":\n",
    "    run2 = client.beta.threads.runs.retrieve(\n",
    "        thread_id=thread_python.id,\n",
    "        run_id=run2.id\n",
    "    )\n",
    "    time.sleep(1)\n",
    "print(\"Run2 completed with status: \" + run2.status)  # 打印执行流的完成状态"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b307d63-1be6-4d4a-bad5-3b9f7a577e94",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "781fd9e1-ce8d-4420-8457-36ebf60464e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在该线程中创建一条信息\n",
    "message = client.beta.threads.messages.create(\n",
    "    thread_id=thread_python.id,\n",
    "    role=\"user\",\n",
    "    content=\"红黑树呢？\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "763e352d-0baa-425c-960a-f863a9cdc8b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建并等待执行流完成，用于处理该线程中的交互和问题解答\n",
    "run = client.beta.threads.runs.create_and_poll(\n",
    "    thread_id=thread_python.id,\n",
    "    assistant_id=assistant_python.id,\n",
    ")\n",
    "\n",
    "print(\"Run completed with status: \" + run.status)  # 打印执行流的完成状态\n",
    "\n",
    "# 如果执行流状态为 \"completed\"（已完成），则获取并打印所有消息\n",
    "if run.status == \"completed\":\n",
    "    messages = client.beta.threads.messages.list(thread_id=thread_python.id)\n",
    "\n",
    "    print(\"\\nMessages:\\n\")\n",
    "    for message in messages:\n",
    "        assert message.content[0].type == \"text\"\n",
    "        print(f\"Role: {message.role.capitalize()}\")  # 角色名称首字母大写\n",
    "        print(\"Message:\")\n",
    "        print(message.content[0].text.value + \"\\n\")  # 每条消息后添加空行以增加可读性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87ce3ccc-58e5-4eeb-bbc1-b3442f4f5818",
   "metadata": {},
   "outputs": [],
   "source": [
    "client.beta.assistants.delete(assistant_python.id)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langChain",
   "language": "python",
   "name": "langchain"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
